package com.asiainfo.complier;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.asiainfo.complier.action.ComplierAction;
import com.asiainfo.complier.action.JavaRunAction;
import com.asiainfo.complier.astyle.AStyle;
import com.asiainfo.complier.codemanger.CodeManager;
import com.asiainfo.complier.common.ComplierInfo;
import com.asiainfo.complier.conf.SysSetting;
import com.asiainfo.complier.editor.CoderEditor;
import com.asiainfo.complier.editor.LineEditor;
import com.asiainfo.complier.editor.ToolTipJTabbedPane;
import com.asiainfo.complier.helper.ComplierErrorHelper;
import com.asiainfo.complier.helper.DroptargetHelper;
import com.asiainfo.complier.helper.StringHelper;
import com.asiainfo.complier.helper.UIHelper;
import com.asiainfo.complier.ui.AboutUsDlg;
import com.asiainfo.complier.ui.FindAndReplaceDlg;
import com.asiainfo.complier.ui.JStatusBar;
import com.asiainfo.complier.ui.JavaSettingDlg;
import com.asiainfo.complier.ui.StatusBarItem;

public class MainApp extends JFrame {

	/**
	 * MainApp
	 * 
	 */
	private static final long serialVersionUID = -5115899596707716747L;
	private CodeManager manager;
	private ToolTipJTabbedPane codeTabbedPane;
	private JPopupMenu popupMenu;
	private StatusBarItem lbLineStatusInfo;
	private FindAndReplaceDlg dlg;
	private JSplitPane splitPane;
	private LineEditor consoleEditor;
	private JTabbedPane consoJTabbedPane;
	private String caption = "java Mini Complier";
	private boolean timeRunning = true;
	private JButton runStatusButton;

	public MainApp() {
		initUI();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		MainApp app = new MainApp();
		// app.setPreferredSize(new Dimension(800, 600));

		app.setSize(800, 600);
		app.centerWindow();
		app.setVisible(true);

	}

	private void initMenu() {
		JMenu fileMenu = new JMenu(UIHelper.getResource("lan_file"));
		fileMenu.setMnemonic(KeyEvent.VK_F);
		JMenuItem newMenuItem = new JMenuItem(UIHelper.getResource("lan_new"));
		newMenuItem.setAccelerator(KeyStroke.getKeyStroke('N',
				java.awt.Event.CTRL_MASK, false));
		newMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				manager.addCoderPane(null, null, lbLineStatusInfo);
			}
		});
		JMenuItem fileOpenMenuItem = new JMenuItem(UIHelper.getResource("lan_open"));
		fileOpenMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-open.png"));
		fileOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke('O',
				java.awt.Event.CTRL_MASK, false));

		fileOpenMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.openFile(MainApp.this, lbLineStatusInfo);
			}
		});
		// save
		JMenuItem saveMenuItem = new JMenuItem(UIHelper.getResource("lan_save"));
		saveMenuItem.setAccelerator(KeyStroke.getKeyStroke('S',
				java.awt.Event.CTRL_MASK, false));
		saveMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				try {
					manager.save(MainApp.this);
				} catch (Exception e1) {

					e1.printStackTrace();
				}
			}
		});
		JMenuItem saveAsOpenMenuItem = new JMenuItem(UIHelper.getResource("lan_save_as"));
		saveAsOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke('S',
				java.awt.Event.CTRL_MASK | Event.SHIFT_MASK, false));
		saveAsOpenMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-saveall.png"));
		saveAsOpenMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				try {
					manager.saveAs(MainApp.this);
				} catch (Exception e1) {

					e1.printStackTrace();
				}
			}
		});
		// exit
		JMenuItem exitOpenMenuItem = new JMenuItem(UIHelper.getResource("lan_exit"));
		exitOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke('X',
				java.awt.Event.ALT_MASK, false));
		exitOpenMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				System.exit(0);
			}
		});
		fileMenu.add(newMenuItem);
		fileMenu.add(fileOpenMenuItem);
		fileMenu.add(new JSeparator());
		fileMenu.add(saveMenuItem);
		fileMenu.add(saveAsOpenMenuItem);
		fileMenu.add(new JSeparator());
		fileMenu.add(exitOpenMenuItem);

		// edit
		JMenu editMenu = new JMenu(UIHelper.getResource("lan_edit"));
		editMenu.setMnemonic(KeyEvent.VK_E);
		JMenuItem copyMenuItem = new JMenuItem(UIHelper.getResource("lan_copy"));
		copyMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-copy.png"));
		copyMenuItem.setAccelerator(KeyStroke.getKeyStroke('C',
				java.awt.Event.CTRL_MASK, false));
		copyMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (manager.getActiveCoderEditor() != null) {
					manager.getActiveCoderEditor().getActiveEditor().copy();

				}

			}
		});
		JMenuItem pasteMenuItem = new JMenuItem(UIHelper.getResource("lan_paste"));
		pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke('V',
				java.awt.Event.CTRL_MASK, false));
		pasteMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-paste.png"));
		pasteMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				if (manager.getActiveCoderEditor() != null) {
					manager.getActiveCoderEditor().getActiveEditor().paste();
				}
			}
		});
		JMenuItem cutMenuItem = new JMenuItem(UIHelper.getResource("lan_cut"));
		cutMenuItem.setAccelerator(KeyStroke.getKeyStroke('X',
				java.awt.Event.CTRL_MASK, false));
		cutMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-cut.png"));
		cutMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (manager.getActiveCoderEditor() != null) {
					manager.getActiveCoderEditor().getActiveEditor().cut();
				}
			}
		});
		editMenu.add(copyMenuItem);
		editMenu.add(pasteMenuItem);
		editMenu.add(cutMenuItem);

		JMenuItem redoMenuItem = new JMenuItem(UIHelper.getResource("lan_redo"));
		redoMenuItem.setAccelerator(KeyStroke.getKeyStroke('U',
				java.awt.Event.CTRL_MASK, false));
		redoMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/redo.png"));
		redoMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				manager.redo();
			}
		});
		JMenuItem undoMenuItem = new JMenuItem(UIHelper.getResource("lan_undo"));
		undoMenuItem.setAccelerator(KeyStroke.getKeyStroke('Z',
				java.awt.Event.CTRL_MASK, false));
		undoMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/undo.png"));
		undoMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				manager.undo();
			}
		});
		editMenu.add(new JSeparator());
		editMenu.add(redoMenuItem);
		editMenu.add(undoMenuItem);

		// find
		JMenuItem findOrReplaceMenuItem = new JMenuItem(UIHelper.getResource("lan_replace_find"));
		findOrReplaceMenuItem.setAccelerator(KeyStroke.getKeyStroke('F',
				java.awt.Event.CTRL_MASK, false));
		findOrReplaceMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (null == dlg) {
					dlg = new FindAndReplaceDlg(MainApp.this, manager);
				}
				dlg.doModal();
			}
		});
		findOrReplaceMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-find.png"));
		JMenuItem findPrevMenuItem = new JMenuItem(UIHelper.getResource("lan_find"));
		findPrevMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3,
				java.awt.Event.CTRL_MASK, false));
		findPrevMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				if (null != dlg) {
					dlg.findPrev();
				}
			}
		});

		JMenuItem findNextMenuItem = new JMenuItem(UIHelper.getResource("lan_find_next"));
		findNextMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3,
				0, false));
		findNextMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (null != dlg) {
					dlg.findNext();
				}
			}
		});
		editMenu.add(new JSeparator());
		editMenu.add(findOrReplaceMenuItem);
		editMenu.add(findPrevMenuItem);
		editMenu.add(findNextMenuItem);
		// sourceMenu
		JMenu sourceMenu = new JMenu(UIHelper.getResource("lan_source"));
		sourceMenu.setMnemonic(KeyEvent.VK_S);
		JMenuItem formatItem = new JMenuItem(UIHelper.getResource("lan_format"));
		formatItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
				java.awt.Event.CTRL_MASK | Event.SHIFT_MASK, false));
		sourceMenu.add(formatItem);
		formatItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				LineEditor editor = manager.getActiveCoderEditor().getEditor();
				if (editor != null) {
					int pos = editor.getCaretPosition();
					String code = editor.getText();

					editor.setText(AStyle.doFormat(code));
					if (pos < editor.getText().length()) {
						editor.moveCaretPosition(pos);
						editor.select(pos, 0);
					}
				}

			}
		});

		// run
		JMenu runMenu = new JMenu(UIHelper.getResource("lan_run"));
		runMenu.setMnemonic(KeyEvent.VK_R);

		JMenuItem complierMenuItem = new JMenuItem(UIHelper.getResource("lan_complier"));
		complierMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F7,
				0, false));
		complierMenuItem.setMnemonic(KeyEvent.VK_F7);
		complierMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				openConsole();
				consoleEditor.setText("Compling.....\n ");
				Thread t = new Thread(new Runnable() {

					public void run() {
						String codePath = manager.getActiveEditorPath();
						if (null != codePath) {
							JavaRunAction runAction = new JavaRunAction();
							String compilerCmd = runAction.getComplierCmd(
									codePath, manager.getPacketName());
							ComplierAction runHelper = new ComplierAction();
							String sourceCode = runHelper.complier(compilerCmd,
									consoleEditor);
							String fileName = manager.getFiletName();
							CoderEditor codeEditor = manager
									.getActiveCoderEditor();
							if (codeEditor != null) {
								ArrayList<ComplierInfo> complierInfo = ComplierErrorHelper
										.getComplierInfo(fileName, sourceCode);

								manager.getActiveCoderEditor().updateErrorInfo(
										complierInfo);

								if (complierInfo != null
										&& complierInfo.size() > 0) {
									codeEditor.getEditor().go2Line(
											complierInfo.get(0).getErrorLine());

								}
							}

						}
					}
				});
				t.start();

			}
		});

		JMenuItem runMenuItem = new JMenuItem(UIHelper.getResource("lan_run"));
		runMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0,
				false));
		runMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				openConsole();
				consoleEditor.setText(" ");
				Thread t = new Thread(new Runnable() {

					public void run() {
						String codePath = manager.getActiveEditorPath();
						if (null != codePath) {
							JavaRunAction runAction = new JavaRunAction();
							// String compilerCmd = runAction.getComplierCmd(
							// codePath, manager.getPacketName());
							ComplierAction runHelper = new ComplierAction();
							runHelper.addRunCallBack(runStatusButton);
							String runCmd = runAction.getRunCmd(codePath,
									manager.getPacketName());
							runHelper.run(runCmd, consoleEditor);

						}
					}
				});
				t.start();

			}
		});

		runMenuItem
				.setIcon(UIHelper.getImageIco("com/asiainfo/images/run.png"));
		JMenuItem debugMenuItem = new JMenuItem(UIHelper.getResource("lan_run"));
		debugMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/debugger.png"));

		runMenu.add(complierMenuItem);
		runMenu.add(runMenuItem);

		// project
		JMenu projectMenu = new JMenu(UIHelper.getResource("lan_project"));
		projectMenu.setMnemonic(KeyEvent.VK_P);
		JMenuItem propertyMenuItem = new JMenuItem(UIHelper.getResource("lan_prefences"));
		propertyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
				java.awt.Event.CTRL_MASK | Event.ALT_MASK, false));

		propertyMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				JavaSettingDlg settingDlg = new JavaSettingDlg(MainApp.this);
				settingDlg.doModal();
			}
		});
		projectMenu.add(propertyMenuItem);

		// help
		JMenu helpMenu = new JMenu(UIHelper.getResource("lan_help"));
		helpMenu.setMnemonic(KeyEvent.VK_H);
		JMenuItem aboutMenuItem = new JMenuItem(UIHelper.getResource("lan_about"));
		aboutMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				AboutUsDlg dlg = new AboutUsDlg(MainApp.this);
				dlg.doModal();
			}
		});
		aboutMenuItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-help.png"));
		helpMenu.add(aboutMenuItem);

		JMenuBar bar = new JMenuBar();
		bar.setBounds(10, 2, -1, getHeight());
		bar.setBorderPainted(false);
		bar.add(fileMenu);
		bar.add(editMenu);
		bar.add(sourceMenu);
		bar.add(runMenu);
		bar.add(projectMenu);
		bar.add(helpMenu);

		setJMenuBar(bar);
	}

	private JPopupMenu initPopMenu() {
		JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem closeItem = new JMenuItem(UIHelper.getResource("lan_bt_close"));
		closeItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.close();
			}
		});
		JMenuItem closeAllItem = new JMenuItem(UIHelper.getResource("lan_bt_close_all"));
		closeAllItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.closeAll();
			}
		});
		JMenuItem closeButthisItem = new JMenuItem(UIHelper.getResource("lan_bt_close_but_this"));
		closeButthisItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.closeButThis();
			}
		});
		JMenuItem openDirButthisItem = new JMenuItem(UIHelper.getResource("lan_bt_open_current_dir"));
		openDirButthisItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-open.png"));
		openDirButthisItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.openDir();
			}
		});

		JMenuItem openOutputDirButthisItem = new JMenuItem("Open File...");
		openOutputDirButthisItem.setIcon(UIHelper
				.getImageIco("com/asiainfo/images/menu-open.png"));
		openOutputDirButthisItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				manager.openOutPutDir();
			}
		});
		popupMenu.add(closeItem);
		popupMenu.add(closeAllItem);
		popupMenu.add(closeButthisItem);
		popupMenu.addSeparator();
		popupMenu.add(openDirButthisItem);
		//popupMenu.addSeparator();
		// popupMenu.add(openOutputDirButthisItem);

		return popupMenu;
	}

	private void initUI() {
		codeTabbedPane = new ToolTipJTabbedPane();
		manager = new CodeManager(codeTabbedPane);
		lbLineStatusInfo = new StatusBarItem("1:1");
		manager.setParentWindow(this);

		Font font = new Font("dialoginput", Font.PLAIN, 12);
		UIHelper.setUIFont(font);
		setIconImage(UIHelper.getImage("com/asiainfo/images/class.png"));
		this.setTitle(caption);
		initMenu();
		popupMenu = initPopMenu();
		JToolBar toolbar = new JToolBar();
		splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);

		JScrollPane cosolJScrollPane = new JScrollPane();
		consoleEditor = new LineEditor();
		consoleEditor.setShowLineNumber(true);
		// consoleEditor.setMargin(new Insets(2, 2, 2, 2));
		cosolJScrollPane.getViewport().add(consoleEditor);
		splitPane.setTopComponent(codeTabbedPane);
		consoJTabbedPane = new JTabbedPane();

		consoJTabbedPane.addTab("Console", cosolJScrollPane);
		splitPane.setBottomComponent(consoJTabbedPane);
		consoJTabbedPane.setVisible(false);
		splitPane.doLayout();
		codeTabbedPane.addChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent paramChangeEvent) {
				String path = manager.getActiveEditorPath();
				if (null != path) {
					setTitle("[ " + path + " ]  - " + caption);
				}

			}
		});

		codeTabbedPane.addMouseListener(new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					int tabIndex = codeTabbedPane.indexAtLocation(e.getX(),
							e.getY());
					if (tabIndex >= 0) {
						popupMenu.show(codeTabbedPane, e.getX(), e.getY());
					}
				}

			}
		});

		DroptargetHelper dropHelper = new DroptargetHelper();
		dropHelper.regsiterDroptarget(this, lbLineStatusInfo, manager);

		SysSetting.MAIN_Frame = this;
		this.setLayout(new BorderLayout());
		this.getContentPane().add(toolbar, BorderLayout.NORTH);
		JComponent statusPanel = initStatusBar();
		this.getContentPane().add(splitPane, BorderLayout.CENTER);
		this.getContentPane().add(statusPanel, BorderLayout.SOUTH);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Thread t = new Thread(new Runnable() {

			public void run() {

				manager.initConfFile(lbLineStatusInfo, MainApp.this);
			}
		});
		t.start();

		this.addWindowListener(new WindowAdapter() {

			public void windowClosing(WindowEvent paramWindowEvent) {
				manager.saveConfFile();
				timeRunning = false;
				if (null != dlg) {
					dlg.dispose();
				}
			}
		});

	}

	private JComponent initStatusBar() {

		JStatusBar statusBar = new JStatusBar();
		statusBar.setLayout(new FlowLayout(FlowLayout.RIGHT));
		final StatusBarItem lbDate = new StatusBarItem(
				StringHelper.toDateString());
		Thread t = new Thread(new Runnable() {

			public void run() {
				while (timeRunning) {
					lbDate.setText(StringHelper.toDateString());
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {

						e.printStackTrace();
					}
				}

			}
		});
		t.start();

		lbDate.setPreferredSize(new Dimension(160, 18));

		lbLineStatusInfo.setPreferredSize(new Dimension(160, 18));
		StatusBarItem cosoleItem = new StatusBarItem();

		ImageIcon icon = UIHelper
				.getImageIco("com/asiainfo/images/console.png");
		cosoleItem.setIcon(icon);
		cosoleItem.setPreferredSize(new Dimension(200, 18));

		cosoleItem.addMouseListener(new MouseAdapter() {

			public void mouseClicked(MouseEvent paramMouseEvent) {
				if (consoJTabbedPane.isVisible()) {
					consoJTabbedPane.setVisible(false);
					splitPane.validate();
				} else {
					openConsole();
				}

			}
		});
		cosoleItem.setText("console[Mini Complier]");
		JPanel runPanel = new JPanel();
		runPanel.setLayout(new BorderLayout());
		runStatusButton = new JButton("");

		JLabel packLabel = new JLabel();
		JLabel rpackLabel = new JLabel();
		packLabel.setPreferredSize(new Dimension(40, 18));
		rpackLabel.setPreferredSize(new Dimension(40, 18));

		runStatusButton.setEnabled(false);
		runPanel.add(packLabel, BorderLayout.WEST);
		runPanel.add(runStatusButton, BorderLayout.CENTER);
		runPanel.add(rpackLabel, BorderLayout.EAST);

		runPanel.setPreferredSize(new Dimension(100, 18));

		statusBar.add(runPanel);
		statusBar.add(cosoleItem);
		statusBar.add(lbLineStatusInfo);
		statusBar.add(lbDate);

		// size
		// Dimension size = new Dimension(800, 640);//
		// Toolkit.getDefaultToolkit().getScreenSize();
		// Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
		// Insets scrInsets =
		// Toolkit.getDefaultToolkit().getScreenInsets(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration());
		// setBounds(scrInsets.left, scrInsets.top, scrSize.width -
		// scrInsets.left - scrInsets.right, scrSize.height - scrInsets.top -
		// scrInsets.bottom);

		return statusBar;
	}

	/**
	 * open console
	 */
	private void openConsole() {
		consoJTabbedPane.setVisible(true);
		double dx = 120.001 / splitPane.getHeight();
		splitPane.setDividerLocation(1 - dx);
		consoJTabbedPane.setPreferredSize(new Dimension(-1, 120));
		splitPane.validate();
	}

	/**
	 * make center screen
	 */
	public void centerWindow() {

		Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
		int dx = size.width / 2 - this.getWidth() / 2;
		int dy = size.height / 2 - this.getHeight() / 2;
		this.setLocation(dx, dy);
	}
}
